import type { PropType } from 'vue'
import type { ExtractProps } from '@/utils/type'
import { OptionNS, PagingNS } from '@/components'
import { useNamespace } from '@/utils'
 
export namespace variables {
  export const ns = useNamespace('Select')
  export const provideName = ns.name + 'Provide'
  export type ProvideContext = {
    isActive(param: OptionNS.Props): boolean
    change(param: OptionNS.Props): void
    props: SelectNS.Props
  }
}
export namespace SelectNS {
  export const name = variables.ns.name
  export const props = {
    modelValue: [...OptionNS.props.value.type, Array<OptionNS.Props['value']>],
    /**
     * 是否多选
     * @默认 false
     */
    multiple: Boolean,
    disabled: Boolean,
    /**
     * 作为 value 唯一标识的键名，绑定值为 object 时必填
     */
    valueKey: String,
    /**
     * 是否可以清空选项
     */
    clearable: Boolean,
    /**
     * 多选时是否将选中值按文字的形式展示
     */
    collapseTags: Boolean,
    /**
     * multiple 属性设置为 true 时，
     * 代表多选场景下用户最多可以选择的项目数， 
     * 为 0 则不限制
     * @默认 0
     */
    multipleLimit: {
      type: Number,
      default: 0
    },
    /**
     * 占位符，默认为 "请选择"
     */
    placeholder: String,
    /**
     * 其中的选项是否从服务器远程加载
     */
    remote: Boolean,
    /**
     * 自定义远程搜索方法
     */
    remoteMethod: Function as PropType<(param: {
      text: string
      pagingRef?: PagingNS.Instance['pagingRef'],
      pageNo: number
      pageSize: number
    }) => any>,
    /**
     * 是否在 remote 为 true 时，给 input 的 onInput 添加防抖事件
     *  @description Function 如果是 函数，那么可以自定义防抖函数
     *    @example (param: { pagingRef }) => debouce(() => pagingRef?.reload(), 300)
     *  @description Number 如果是数字，那么只能设定防抖间隔时间
     *    @example 300
     *  @description debouce 为 undefined 时，onInput 会触发 () => pagingRef?.reload()
     */
    debouce: [Function, Number] as PropType<((param: { pagingRef?: ZPagingRef }) => () => void) | number>,
    /**
     * 下拉框的宽度是否与输入框相同
     */
    fitInputWidth: Boolean,
    /**
     * paging 参数
     */
    pagingProps: Object as PropType<PagingNS.Props>,
  }
  type BaseProps = ExtractProps.Types<typeof props>
  export const emits = {
    'update:modelValue': (_val: BaseProps['modelValue']) => true,
    change: (_val: BaseProps['modelValue']) => true,
    /**
     * 下拉框 options 出现和隐藏时调用
     * @param _show 
     */
    visibleChange: (_show: boolean) => true,
    /**
     * 清空所有选项
     */
    clear: () => true,
    /**
     * 在多选模式下删除了一个选项
     */
    removeItem: (_item: OptionNS.Props) => true,
    /**
     * 选项超出限制
     */
    exceed: (_item: OptionNS.Props, _list: Array<OptionNS.Props['value']>) => true,
    /**
     * remote 为 true，会出现一个 input 框，这个 input 获得焦点会触发此回调
     */
    focus: (_e: Event) => true,
    /**
     * remote 为 true，会出现一个 input 框，这个 input 失去焦点会触发此回调
     */
    blur: (_e: Event) => true
  }
  export type Props = BaseProps & PartialEmits<typeof emits>
  export type Slots = PagingNS.Slots & {
    label: (options: OptionNS.Props) => void
    /**
     * @param param.isArrow 如果为 true，则是箭头，否则 ×
     */
    suffix: (param: { isArrow: boolean }) => void
  }
  export const Component = <{
    new(): {
      $props: Props
      $slots: Slots
    }
  }>{}
}